<!DOCTYPE html>
<html xmlns:v-on="http://www.w3.org/1999/xhtml" xmlns:v="http://www.w3.org/1999/xhtml">
<head>
    <title>SAPI. A simple api scanner</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="//cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="//cdn.bootcss.com/vue/2.2.2/vue.min.js"></script>
    <script src="//cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script>

    <style>
        .btn.active,.btn:active:focus,.btn:focus {outline:medium}
         textarea,input,button{background:none;outline:medium;border:1px black solid;}
        .input_st {border: 0px;border-bottom: 1px solid #CCCCCC;background-color:#F8F8F8;}
        .input_title {min-width: 430px;}
        .input_st:hover {border: 1px;border-bottom: 1px solid #CCCCCC;background-color:#F8F8F8;}
        input::-webkit-input-placeholder{color:#DAA520;font-style: oblique;}
        input::-moz-placeholder{   /* Mozilla Firefox 19+ */color:#DAA520;font-style: oblique;}
        input:-moz-placeholder{    /* Mozilla Firefox 4 to 18 */color:#DAA520;font-style: oblique;}
        input:-ms-input-placeholder{  /* Internet Explorer 10-11 */color:#DAA520;font-style: oblique;}
        *{-webkit-border-radius: 0 !important;-moz-border-radius: 0 !important;border-radius: 0 !important;}
        .codeData{min-height: 220px;max-height: 220px;width: 100%;border: 1px solid #CCC;background: #f5f5f5;overflow:auto}
        .form-control{border: 1px solid inherit;}
         .btn{border: 1px solid inherit;}
        .input-md {border: 1px solid #F8F8F8;}
        .modal{color: #696969}
        .jumbotron {
            padding-top: 15px;
            padding-bottom: 10px;
            margin-bottom: 10px;
            color: inherit;
            background-color: #F8F8F8
        }

        .ObjectBrace{color:#0a0;font-weight:bold}.ArrayBrace{color:#03f;font-weight:bold}.PropertyName{color:#c00;font-weight:bold}.String{color:#077}.Number{color:#a0a}.Boolean{color:#00f}.Function{color:#a63;text-decoration:italic}.Null{color:#00f}.Comma{color:#000;font-weight:bold}PRE.CodeContainer{margin-top:0;margin-bottom:0}

    </style>
</head>
<body>
​<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand " href="#"><span class="glyphicon glyphicon-leaf"></span>SAPI</a>
        </div>
        <div>
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">API</a></li>
                <li><a href="/faq"><span class="glyphicon glyphicon-question-sign"></span></a></li>
            </ul>
        </div>
    </div>
</nav>

<div class="container" style="padding-top: 35px;min-height: 400px;">
    <div id="apiList" class="row" v-cloak>
        <div class="jumbotron" v-for="data in apiList">
            <div style="margin-bottom: 12px">
                <div>接口URL： {{data.url}}</div>
                <div class="btn-group pull-right">
                    <button type="button" class="btn btn-success" v-on:click="openDebug(data)" data-toggle="modal" data-target="#debugModal">
                        <span class="glyphicon glyphicon-play"></span>
                    </button>
                </div>
            </div>

            <span >
                <div>请求类型：{{data.requestType}}</div>
            </span>

            <div class="table-responsive">
            <table class="table table-bordered">
            <caption>接口参数：</caption>
            <thead>
            <tr>
                <th style="width:50%">字段</th>
                <th style="width:50%">类型</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="field in data.fieldList">
                <td>{{field.name}}</td>
                <td>{{field.type}}</td>
            </tr>

            </tbody>
        </table>
            </div>
        </div>
        <nav>
            <ul class="pager">
                <li><a v-on:click="jumpPage(-1)">上一页</a></li>
                <li>{{currentPage}}/{{totalPage}}</li>
                <li><a v-on:click="jumpPage(1)">下一页</a></li>
            </ul>
        </nav>

    </div>


    <!-- 模态框（Modal） -->
    <div class="modal fade" id="debugModal" v-cloak tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static">
        <div class="modal-dialog" style="width:65%;">
            <form id="modal-form"  enctype="multipart/form-data">
            <div class="modal-content">
                <div class="modal-header" style="padding: 10px">
                    <button type="reset" class="close" data-dismiss="modal" aria-hidden="true" v-on:click="close">
                        <span class="glyphicon glyphicon-remove-circle"></span>
                    </button>
                    <h4 class="modal-title" id="myModalLabel">API Testing</h4>
                </div>
                <div class="modal-body" style="padding: 5px">
                    <div class="input-group">
                        <div class="input-group-btn">
                            <button type="button" class="btn btn-default">{{requestType}}</button>
                            <button type="button" class="btn btn-default dropdown-toggle"
                                    data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <span class="caret"></span>
                                <span class="sr-only"></span></button>
                            <ul class="dropdown-menu">
                                <li><a v-on:click="reqType('POST')">POST   </a></li>
                                <li><a v-on:click="reqType('GET')">GET  </a></li>
                                <li><a v-on:click="reqType('PUT')">PUT   </a></li>
                                <li><a v-on:click="reqType('DELETE')">DELETE</a></li>
                            </ul>
                        </div><!-- /btn-group -->

                        <input type="text" class="form-control" placeholder="Enter your Request URL" v-model="curl">
                        <span class="input-group-btn">
                            <button class="btn btn-primary" type="button" v-on:click="doDebug(debugData)">Send</button>
                        </span>
                    </div><!-- /input-group -->
                    <br>
                    <table class="table table-bordered">
                        <thead>
                        <tr>
                            <th style="width:25%">Parameter</th>
                            <th style="width:50%">Value</th>
                            <th style="width:25%">Data Type</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="field in debugData.fieldList">
                            <td>{{field.name}}</td>
                            <td v-if="field.type!='MultipartFile'"><input type="text" class="form-control input-sm input-md" v-model="field.value" placeholder="Value"></td>
                            <td v-else><input type="file" :name="field.name" ref="field.name" class="form-control input-sm input-md" v-model="field.value" @change="changeFile(field,$event)" ></td>
                            <td>{{field.type}}</td>
                        </tr>
                        </tbody>
                    </table>
                    <div class="btn-group" role="group" aria-label="...">
                        <button type="button" class="btn btn-default" v-on:click="changeDataStyle('JSON')" :class="{'active':jsonActive===true}">JSON</button>
                        <button type="button" class="btn btn-default" v-on:click="changeDataStyle('XML')" :class="{'active':xmlActive===true}">XML</button>
                    </div>
                        <pre id="returnData" class='CodeContainer codeData'>
                        </pre>
                    <span class="label label-success" v-if="resultMsg=='200'"><span class="glyphicon glyphicon-ok-circle"></span>Status: {{resultMsg}} OK</span>
                    <span class="label label-warning" v-else-if="resultMsg!='200'"><span class="glyphicon glyphicon-exclamation-sign"></span>Status: {{returnData.status}} Error: {{returnData.error}}</span>

                </div>

            </div><!-- /.modal-content -->
            </form>
        </div><!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->
</div>

<footer class="footer" style="border-top: 1px solid #CCCCCC">
    <div class="container text-center ">
        <br>
        <span>SAPI is a simple api starter for spring</span>
        <h6> SAPI V1.2 ©️ xiaour</h6>
    </div>
</footer>
</body>
<script type="text/javascript">
    //着色
    window.TAB = "    ";
    function IsArray(obj) {
        return obj &&
            typeof obj === 'object' &&  typeof obj.length === 'number' && !(obj.propertyIsEnumerable('length'));
    }

    function Process(continner,json) {
        document.getElementById(continner).style.display = "block";
        if (json == "") {
            json = '""';
        }
        var obj = eval("[" + json + "]");
        var html = ProcessObject(obj[0], 0, false, false, false);
        document.getElementById(continner).innerHTML =html;

    }

    function ProcessObject(obj, indent, addComma, isArray, isPropertyContent) {
        var html = "";
        var comma = (addComma) ? "<span class='Comma'>,</span> ": "";
        var type = typeof obj;
        if (IsArray(obj)) {
            if (obj.length == 0) {
                html += GetRow(indent, "<span class='ArrayBrace'>[ ]</span>" + comma, isPropertyContent);
            } else {
                html += GetRow(indent, "<span class='ArrayBrace'>[</span>", isPropertyContent);
                for (var i = 0; i < obj.length; i++) {
                    html += ProcessObject(obj[i], indent + 1, i < (obj.length - 1), true, false);
                }
                html += GetRow(indent, "<span class='ArrayBrace'>]</span>" + comma);
            }
        } else {
            if (type == "object" && obj == null) {
                html += FormatLiteral("null", "", comma, indent, isArray, "Null");
            } else {
                if (type == "object") {
                    var numProps = 0;
                    for (var prop in obj) {
                        numProps++;
                    }
                    if (numProps == 0) {
                        html += GetRow(indent, "<span class='ObjectBrace'>{ }</span>" + comma, isPropertyContent)
                    } else {
                        html += GetRow(indent, "<span class='ObjectBrace'>{</span>", isPropertyContent);
                        var j = 0;
                        for (var prop in obj) {
                            html += GetRow(indent + 1, '<span class="PropertyName">"' + prop + '"</span>: ' + ProcessObject(obj[prop], indent + 1, ++j < numProps, false, true))
                        }
                        html += GetRow(indent, "<span class='ObjectBrace'>}</span>" + comma);
                    }
                } else {
                    if (type == "number") {
                        html += FormatLiteral(obj, "", comma, indent, isArray, "Number");
                    } else {
                        if (type == "boolean") {
                            html += FormatLiteral(obj, "", comma, indent, isArray, "Boolean");
                        } else {
                            if (type == "function") {
                                obj = FormatFunction(indent, obj);
                                html += FormatLiteral(obj, "", comma, indent, isArray, "Function");
                            } else {
                                if (type == "undefined") {
                                    html += FormatLiteral("undefined", "", comma, indent, isArray, "Null");
                                } else {
                                    html += FormatLiteral(obj, '"', comma, indent, isArray, "String");
                                }
                            }
                        }
                    }
                }
            }
        }
        return html;
    };

    function FormatLiteral(literal, quote, comma, indent, isArray, style) {
        if (typeof literal == "string") {
            literal = literal.split("<").join("&lt;").split(">").join("&gt;");
        }
        var str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
        if (isArray) {
            str = GetRow(indent, str);
        }
        return str;
    }
    function FormatFunction(indent, obj) {
        var tabs = "";
        for (var i = 0; i < indent; i++) {
            tabs += window.TAB;
        }
        var funcStrArray = obj.toString().split("\n");
        var str = "";
        for (var i = 0; i < funcStrArray.length; i++) {
            str += ((i == 0) ? "": tabs) + funcStrArray[i] + "\n";
        }
        return str;
    }

    function GetRow(indent, data, isPropertyContent) {
        var tabs = "";
        for (var i = 0; i < indent && !isPropertyContent; i++) {
            tabs += window.TAB;
        }
        if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
            data = data + "\n";
        }
        return tabs + data;
    };

    var isXML = function(elem){
        var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
        return documentElement ? documentElement.nodeName !== "HTML" : false;
    };

    function formatXML(continner,content) {
        var xml_doc = (new DOMParser()).parseFromString(content.replace(/[\n\r]/g, ""), 'text/xml');

        function build_xml(index, list, element) {
            var t = [];
            for (var i = 0; i < index; i++) {
                t.push('&nbsp;&nbsp;&nbsp;&nbsp;');
            }
            t = t.join("");
            list.push(t + '&lt;<span class="code-key">'+ element.nodeName +'</span>&gt;\n');
            for (var i = 0; i < element.childNodes.length; i++) {
                var nodeName = element.childNodes[i].nodeName;
                if (element.childNodes[i].childNodes.length === 1) {
                    var value = element.childNodes[i].childNodes[0].nodeValue;
                    var value_color = !isNaN(Number(value)) ? 'code-number' : 'code-string';
                    var value_txt = '<span class="'+ value_color +'">' + value + '</span>';
                    var item = t + '&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span class="code-key">' + nodeName +
                        '</span>&gt;' + value_txt + '&lt;/<span class="code-key">' + nodeName + '</span>&gt;\n';

                    list.push(item);
                } else {
                    build_xml(++index, list, element.childNodes[i]);
                }
            }
            list.push(t + '&lt;/<span class="code-key">'+ element.nodeName +'</span>&gt;\n');
        }

        var list = [];
        build_xml(0, list, xml_doc.documentElement);

        document.getElementById(continner).innerHTML = list.join("");

        return list.join("");
    };


    $(function(){
        vm = new Vue({
            el:'#apiList',
            data:{apiList : [],
                currentPage:1,
                totalPage:1
            },mounted:function () {
                this.getmc(1);
            },

            methods: {
                openDebug: function (data) {
                    var url = window.location.href;
                    vm2.curl=url.split("/sapi")[0]+data.url;
                    vm2.debugData=copy(data);
                    for(var i=0;i<vm2.debugData.fieldList.length;i++){
                       data.fieldList[i].value="";
                    }
                    vm2.returnData="";
                    vm2.reqHeaders=[{name:null,value:null}];
                },
                jumpPage:function(condition){
                    vm.currentPage=vm.currentPage+condition;
                    console.log(vm.currentPage)
                    if(vm.currentPage==0){
                        vm.currentPage=vm.currentPage+1;
                        alert("已经是第一页了！");
                        return;
                    }
                    if(vm.currentPage>vm.totalPage){
                        alert("已经是最后一页了！");
                        vm.currentPage=vm.currentPage-1;
                        return;
                    }
                    this.getmc(vm.currentPage);
                },getmc:function (page){
                    var url="apiList";
                    if(page!=null){
                        url+="?pageNum="+page
                    }
                    this.$http.get(url).then(function(res) {
                            vm.apiList = res.data.apiList;
                            vm.totalPage = res.data.totalPage>0?res.data.totalPage:1;
                        },
                        function (err){
                            console.log(err);
                        } );

                }
            }
        });

        vm2 = new Vue({
            el:'#debugModal',
            data:{debugData:"",
                requestType:"POST",
                returnData:"",
                reqHeaders:[],
                curl:"",
                resultMsg:"200",
                formData:new FormData(),
                jsonActive:false,
                xmlActive:false
            },
            methods: {
                getRequestType:function () {
                    alert(vm2.debugData);
                },
                changeDataStyle:function(style){
                if(style=="XML"){
                    try {
                        if(isXML(vm2.returnData)) {
                            formatXML("returnData", vm2.returnData);
                            vm2.xmlActive = true;
                            vm2.jsonActive = false;
                        }else{
                            document.getElementById("returnData").innerHTML =vm2.returnData;
                        }
                    }catch (err){
                        try {
                            Process("returnData", vm2.returnData);
                            vm2.xmlActive = false;
                            vm2.jsonActive = true;
                        }catch (err2){
                            document.getElementById("returnData").innerHTML =vm2.returnData;
                        }
                    }

                }
                if(style=="JSON"){
                    try {
                        Process("returnData", vm2.returnData);
                        vm2.xmlActive=false;
                        vm2.jsonActive=true;
                    }catch (err){
                        if(isXML(vm2.returnData)) {
                            formatXML("returnData",vm2.returnData);
                            vm2.xmlActive=true;
                            vm2.jsonActive=false;
                        }else{
                            document.getElementById("returnData").innerHTML =vm2.returnData;
                        }
                    }
                }

            }, doDebug: function (data) {

                    vm2.returnData = "Requesting...";
                    if(vm2.requestType=="GET"){

                        var tempUrl="";

                        for(var i=0;i<data.fieldList.length;i++){
                            if(data.fieldList[i].type!="MultipartFile"&&data.fieldList[i].value!=undefined){
                               tempUrl=tempUrl+data.fieldList[i].name+"="+data.fieldList[i].value+"&";
                            }
                        }

                        this.$http.get(vm2.curl+"?"+tempUrl,vm2.reqHeaders)
                            .then(function (res) {
                                    vm2.returnData=res.bodyText;
                                    vm2.resultMsg="200"
                                    vm2.changeDataStyle("JSON");
                                },
                                function (err){
                                    vm2.returnData=err.body;
                                    vm2.resultMsg=err.status;
                                } );
                    }

                    if(vm2.requestType=="POST"){

                        for(var i=0;i<data.fieldList.length;i++){
                            if(data.fieldList[i].type!="MultipartFile"&&data.fieldList[i].value!=undefined){
                                vm2.formData.delete(data.fieldList[i].name);
                                vm2.formData.append(data.fieldList[i].name, data.fieldList[i].value);
                            }
                        }

                        this.$http.post(vm2.curl,vm2.formData,vm2.reqHeaders)
                            .then(function (res) {
                                    vm2.returnData=res.bodyText;
                                    vm2.resultMsg="200"
                                    vm2.changeDataStyle("JSON");
                                },
                                function (err){
                                    vm2.returnData=err.body;
                                    vm2.resultMsg=err.status;
                                } );

                    }
                },
                reqType:function (type) {
                    vm2.requestType=type;
                },
                addHeaders:function (data) {
                    var header=vm2.reqHeaders;
                    var flag=1;
                    for(var i=0;i<header.length;i++){
                        if(header[i].name==undefined||header[i].name=="") {
                            flag=2
                        }
                    }
                    //如果Key都有值，则添加一行新的
                    if(flag==1){
                        vm2.reqHeaders.push({name:null,value:null});
                    }

                },close:function () {
                    vm2.debugData="";
                },
                changeFile:function(data,event){
                    vm2.formData.delete(data.name);
                    var deviceFile = event.target.files;
                    for(var i=0;i<deviceFile.length;i++){
                        vm2.formData.append(data.name, deviceFile[i]);
                    }
                }

            }
        });

    });

    function copy(obj){
        var newobj = {};
        for ( var attr in obj) {
            newobj[attr] = obj[attr];
        }
        return newobj;
    }

</script>
</html>
